﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Rendering.Universal;
using ZyGame.Drawing;
using ZyGame.Transport;
using ZyGame.Transport.Common;
using ZyGame.Transport.TCP;
using ZyGame.Transport.UDP;
using ZyGame.Transport.Web;

namespace ZyGame.Game
{
    public class World : IDisposable
    {
        public Camera camera { get; private set; }
        private List<Camera> cameras = new List<Camera>();
        private List<ILogicSystem> _systems = new List<ILogicSystem>();

        public World()
        {
            
        }

        public virtual void Reload()
        {
           
        }

        public virtual void Awake()
        {
            this.SetWorldMainCamera(new GameObject("Camera_" + this.GetType().Name).AddComponent<Camera>(), true);
        }

        public virtual void Update()
        {
        }

        public virtual void FixedUpdate()
        {
            if (_systems.Count is 0)
            {
                return;
            }

            try
            {
                for (int i = 0; i < _systems.Count; i++)
                {
                    _systems[i].Exexut(this);
                }
            }
            catch (Exception e)
            {
                Client.Console.WriteLine(e);
                throw;
            }
        }

        public virtual void LateUpdate()
        {
        }

        public void LoadLogicSystem<T>() where T : ILogicSystem
        {
            LoadLogicSystem(typeof(T));
        }

        public void LoadLogicSystem(Type type)
        {
            if (typeof(ILogicSystem).IsAssignableFrom(type) is false)
            {
                throw new NotImplementedException(nameof(ILogicSystem));
            }

            ILogicSystem logicSystem = (ILogicSystem)Activator.CreateInstance(type);
            _systems.Add(logicSystem);
        }

        public void UnloadLogicSystem<T>() where T : ILogicSystem
        {
            UnloadLogicSystem(typeof(T));
        }

        public void UnloadLogicSystem(Type type)
        {
            if (typeof(ILogicSystem).IsAssignableFrom(type) is false)
            {
                return;
            }

            for (int i = 0; i < _systems.Count; i++)
            {
                if (_systems[i].GetType() != type)
                {
                    continue;
                }

                _systems.Remove(_systems[i]);
            }
        }

        public void SetWorldMainCamera(Camera camera, bool isUsePostProcessin)
        {
            this.camera = camera;
            camera.cullingMask = 1 << 0;
            camera.GetUniversalAdditionalCameraData().volumeLayerMask = 1 << 0;
            camera.GetUniversalAdditionalCameraData().renderType = CameraRenderType.Overlay;
            camera.GetComponent<UniversalAdditionalCameraData>().renderPostProcessing = isUsePostProcessin;
            AddCamera(CameraSort.GameWorld, camera);
            GameObject.DontDestroyOnLoad(this.camera.gameObject);
        }

        public void AddCamera(CameraSort sort, Camera camera)
        {
            AddCamera((int)sort, camera);
        }

        public void AddCamera(int sort, Camera camera)
        {
            if (camera is null)
            {
                Client.Console.WriteLine("not camera");
                return;
            }

            cameras.Add(camera);
            WorldManager.instance.AddCamera(sort, camera);
        }

        public void RemoveCamera(Camera camera)
        {
            if (cameras.Contains(camera))
            {
                cameras.Remove(camera);
            }

            WorldManager.instance.UniversalData.cameraStack.Remove(camera);
        }

        public virtual void Enable()
        {
            TransformComponent[] transformComponents = this.GetComponents<TransformComponent>();

            if (transformComponents is null || transformComponents.Length is 0)
            {
                return;
            }

            for (int i = 0; i < transformComponents.Length; i++)
            {
                if (transformComponents[i] is null)
                {
                    continue;
                }

                transformComponents[i].gameObject.SetActive(true);
            }
        }

        public virtual void Disable()
        {
            TransformComponent[] transformComponents = this.GetComponents<TransformComponent>();

            if (transformComponents is null || transformComponents.Length is 0)
            {
                return;
            }

            for (int i = 0; i < transformComponents.Length; i++)
            {
                if (transformComponents[i] is null)
                {
                    continue;
                }

                transformComponents[i].gameObject.SetActive(false);
            }
        }

        public virtual void Clear()
        {
            EntityManager.instance.Clear(this.GetType().Name);
            _systems.ForEach(x => x.Dispose());
            _systems.Clear();
        }

        public virtual void Dispose()
        {
            EntityManager.instance.Clear(this.GetType().Name);
            cameras.ForEach(x => WorldManager.instance.RemoveCamera(x));
            camera = null;
        }
    }
}